package info.niwota.frames.web;

import info.niwota.commons.acl.AccessControl;
import info.niwota.frames.Debug;
import info.niwota.frames.FrameHelper;
import info.niwota.frames.ImageFrame;
import info.niwota.webapp.WebUtils;
import info.niwota.webapp.acl.CryptoHelper;
import info.niwota.webapp.acl.PermStore;

import java.io.File;
import java.net.URLDecoder;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONObject;

import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

public class FrameObject {

	private static final String TAG = "FrameObject";
	
	public static final String NAME = "frame";
		
	private Context ctx;
	
	
	public FrameObject(Context ctx) {
		this.ctx = ctx;
	}

	public Object listFrames(JSONObject param, Uri uri) throws Exception {
		if (Debug.DEBUG) {
			Log.d(TAG, "listFrames param: "+ param +" uri: " + uri);
		}
		
		String group = uri.getQueryParameter("group");
		String user = uri.getQueryParameter("user");
		String peer = uri.getQueryParameter("peer");
		boolean info = Boolean.parseBoolean(uri.getQueryParameter("info"));
		
		int g = (TextUtils.isEmpty(group) ? AccessControl.ACCESS_PUBLIC
				: Integer.parseInt(group));
		
		boolean local = WebUtils.isLocal(uri);
		
		if (local && info) {
			JSONObject jo = FrameHelper.queryFrames(ctx);
			return jo;
		}
		
		if (local) {
			JSONObject jo = FrameHelper.queryFrames(ctx);
			JSONArray list = new JSONArray();
			
			File[] files = FrameHelper.list(ctx);
			for (int i = 0; i < files.length; i++) {
				File f = files[i];
				final String label = f.getName();
				if (!canAccess(g, user, label)) {
					continue;
				}
				JSONObject frame = new JSONObject();
				frame.put("label", label);
				frame.put("lastModified", f.lastModified());
				list.put(frame);
			}
			jo.put("frames", list);
			return jo;
		} else {
			JSONObject jo = FrameHelper.getPeerFrames(ctx, peer);
			jo.put("peer", peer);
			return jo;
		}
	}

	public Object loadFrame(JSONObject param, Uri uri) throws Exception {
		if (Debug.DEBUG) {
			Log.d(TAG, "loadFrame param: "+ param +" uri: " + uri);
		}
		
		String label = URLDecoder.decode(uri.getQueryParameter("label"));
		String group = uri.getQueryParameter("group");
		String user = uri.getQueryParameter("user");
		
		String peer = uri.getQueryParameter("peer");
		
		int g = (TextUtils.isEmpty(group) ? AccessControl.ACCESS_PUBLIC
				: Integer.parseInt(group));

		// 
		if (!canAccess(g, user, label)) {
			throw new Exception("Accessed denied");
		}
		
		if (WebUtils.isLocal(uri)) {
			ImageFrame frame = FrameHelper.loadLocalFrame(ctx, label);
			List<Uri> uris = frame.getReferences();
			int size = uris.size();
			//
			JSONArray list = new JSONArray();
			if (size > 0) {
				for (int i = 0; i < size; i++) {
					final JSONObject jo = new JSONObject();
					
					Uri u = uris.get(i);
					String path =  u.getPath();
					//attach the label to the uri for perm check later when the uri is accessed
					String hash = CryptoHelper.hash(path, label, g, user, true);
					//String q = "?label="+label+"&hash="+hash;
					//
					jo.put("uri", u.toString());
					jo.put("hash", hash);
					
					list.put(jo);
				}
			}
			
			JSONObject jo = new JSONObject();
			jo.put("label", label);
			jo.put("lastModified", frame.getLastModified());
			jo.put("list", list);
			jo.put("total", size);
			jo.put("peer", peer);
			
			return jo;
		} else {
			long lastModified = parseLong(uri.getQueryParameter("lastModified"), 0);
			return FrameHelper.getPeerFrame(ctx, peer, label, lastModified);
		}
	}

	private long parseLong(String s, long def) {
		try {
			return Long.parseLong(s);
		} catch (Exception e) {
			//
		}
		return def;
	}

	private boolean canAccess(int group, String user, String label) {
		String[] pa = PermStore.getPerm(ctx, label);
		String perm = pa[0];
		String emails = pa[1];
		
		return AccessControl.canAccess(group, user, label, perm, emails);
	}
}
